home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Telnet Server 1.0 / network.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-14  |  9.2 KB  |  354 lines  |  [TEXT/KAHL]

  1. /*
  2. Copyright © 1994 Mikhail Fridberg. Part of this code is copyrighted by Steve Falkenburg
  3.  
  4. Telnet-based talk server/client
  5.     
  6. connection management is done through the use of Operating System queues to simplify tracking
  7. and usage.
  8. */
  9.  
  10. #include <CommResources.h>
  11. #include <Terminals.h>
  12. #include <Connections.h>
  13.  
  14. #include <Processes.h>
  15. #include <MacTCPCommonTypes.h>
  16. #include <TCPPB.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <errno.h>
  20. #include <time.h>
  21. #include <stddef.h>
  22. #include <string.h>
  23. #include "const.h"
  24. #include "events.h"
  25. #include "globals.h"
  26. #include "utils.h"
  27. #include "queues.h"
  28. #include "network.h"
  29. #include "main.h"
  30. #include "MacSocket.h"
  31.  
  32. long recve (TCPiopb *pBlock, char *buf, long len, long flags);
  33. void StartListener(TCPiopb *pBlock);
  34. void ListenerCompletion(MyQElemPtr iopb);
  35. pascal void ResvCompRoutine(MyQElemPtr iopb);
  36. //void SendData(TCPiopb *pBlock,StringPtr data);
  37. extern    short        gRefNum;
  38. Boolean                gNoSendDataPending = TRUE;
  39.  
  40. /*    initialize TCP/IP driver and create our queues, putting them on the unused list
  41. */
  42.  
  43. OSErr InitNetwork(void)
  44. {
  45.     OSErr err;
  46.     TCPiopb *pBlock;
  47.     short i;
  48.     
  49.     err = OpenDriver("\p.ipp",&gTcpDrvrRef);
  50.     gRefNum = gTcpDrvrRef;
  51.     if (err!=noErr)
  52.         return err;
  53.     
  54.     for (i=0; i<kNumConnections; i++) {
  55.         pBlock = (TCPiopb *)GetUnusedPBlock();
  56.         if (pBlock)
  57.             StartListener(pBlock);
  58.     }
  59.     
  60.     return noErr;
  61. }
  62.  
  63.  
  64. /*    creates a connection end and assigns it to listen for an incoming connection on our
  65.     network port.
  66. */
  67.  
  68. void StartListener(TCPiopb *pBlock)
  69. {
  70.     Ptr rcvBuff;
  71.     OSErr err;
  72.         
  73.     rcvBuff = NewPtr(kRcvBuffSize);
  74.     if (MemError()!=noErr)
  75.         DoError(MemError());
  76.     
  77.     /* create a network stream */
  78.     
  79.     pBlock->csCode = TCPCreate;
  80.     pBlock->ioCRefNum = gTcpDrvrRef;
  81.     pBlock->csParam.create.rcvBuff = rcvBuff;
  82.     pBlock->csParam.create.rcvBuffLen = kRcvBuffSize;
  83.     pBlock->csParam.create.notifyProc = nil;
  84.     err = PBControl(pBlock,false);
  85.     if (err!=noErr)
  86.         DoError(err);
  87.     
  88.     /* create a listener */
  89.     
  90.     pBlock->csCode = TCPPassiveOpen;
  91. #ifdef __SYSEQU__
  92.     ((MyQElemPtr)pBlock)->savedA5 = *(long *)CurrentA5;
  93. #else    
  94.     ((MyQElemPtr)pBlock)->savedA5 = (long)CurrentA5;
  95. #endif
  96.     pBlock->ioCompletion = (ProcPtr)ListenerCompletion;
  97.     pBlock->csParam.open.ulpTimeoutValue = 0;
  98.     pBlock->csParam.open.ulpTimeoutAction = 1;
  99.     pBlock->csParam.open.validityFlags = 0xC0;
  100.     pBlock->csParam.open.commandTimeoutValue = 0;
  101.     pBlock->csParam.open.remoteHost = 0;
  102.     pBlock->csParam.open.remotePort = 0;
  103.     pBlock->csParam.open.localHost = 0;
  104.     pBlock->csParam.open.localPort = kGreetingPort;
  105.     pBlock->csParam.open.tosFlags = 0;
  106.     pBlock->csParam.open.precedence = 0;
  107.     pBlock->csParam.open.dontFrag = 0;
  108.     pBlock->csParam.open.timeToLive = 0;
  109.     pBlock->csParam.open.security = 0;
  110.     pBlock->csParam.open.optionCnt = 0;
  111.     pBlock->csParam.receive.rcvBuffLen = 0L;
  112.     PBControl(pBlock,true);
  113.  
  114.     gRunning++; // increment count of running parameter blocks
  115. }
  116.  
  117.  
  118. /*    called to release all network resources in response to a quit
  119. */
  120.  
  121. void CloseNetwork(void)
  122. {
  123.     THz theZone;
  124.     short drvrRefNum;
  125.     OSErr err;
  126.     TCPiopb tcpBlock;
  127.     StreamPtr *curStream;
  128.     long theStream;
  129.  
  130.     theZone = ApplicZone();
  131.     
  132.     tcpBlock.ioCRefNum = gTcpDrvrRef;
  133.     tcpBlock.csCode = TCPGlobalInfo;
  134.     err = PBControl((ParmBlkPtr)&tcpBlock,false);
  135.     if (err!=noErr)
  136.         return;
  137.     
  138.     curStream = *tcpBlock.csParam.globalInfo.tcpCDBTable;
  139.     while (*curStream) {
  140.     
  141.         theStream = *curStream;
  142.         
  143.         if (PtrZone((Ptr)theStream)==theZone) {                // only release streams in our heap 
  144.  
  145.             tcpBlock.csCode = TCPStatus;
  146.             tcpBlock.tcpStream = theStream;
  147.             err = PBControl((ParmBlkPtr)&tcpBlock,false);
  148.  
  149.             // abort connection 
  150.             
  151.             tcpBlock.csCode = TCPAbort;
  152.             tcpBlock.tcpStream = theStream;
  153.             err = PBControl((ParmBlkPtr)&tcpBlock,false);
  154.             
  155.             // release stream
  156.             
  157.             tcpBlock.csCode = TCPRelease;
  158.             tcpBlock.tcpStream = theStream;
  159.             err = PBControl((ParmBlkPtr)&tcpBlock,false);
  160.         }
  161.         
  162.         curStream++;
  163.     }
  164. }
  165.  
  166.  
  167. /*    this completion routine will be called when one of the listeners gets a connection from a
  168.     remote machine.  since we're using OS queues dispatched from the main event loop, we just
  169.     take the parameter block and put it on the completed queue.  if running seven, we call
  170.     WakeUpProcess() to return control to the application
  171. */
  172.  
  173. void ListenerCompletion(MyQElemPtr iopb)
  174. {
  175.     long saveA5;
  176.     ProcessSerialNumber currentProc;
  177.     
  178.     saveA5 = SetA5(iopb->savedA5);
  179.     
  180.     StoreCompletedPBlock(iopb);
  181.     gRunning--;
  182.     
  183.     if (gRunningSeven) {
  184.         WakeUpProcess(&gOurPSN);
  185.     }
  186.     
  187.     SetA5(saveA5);
  188. }
  189.  
  190.  
  191. /*    this routine is called from the event dispatcher of the event loop to continue processing
  192.     of completed listens received at interrupt time from ListenerCompletion.  We send them
  193.     some data, close the connection, and restart the listener, putting it back on MacTCP's queue
  194. */
  195.  
  196. void ProcessConnection(MyQElemPtr iopb)
  197. {    
  198. //    Point            where;            // For choose dialog    
  199.     int                procID;
  200.     WindowPtr        windowRec, windowSend;        // the window to create            
  201.     Rect            theRectRec, theRectSend;    // for the terminal bounds        
  202.     Str255            toolname = "\pVT102 Tool";
  203.     char            *configStr = "FontSize 9 Width 80 Cursor Underline Online True LocalEcho True AutoRepeat True RepeatControls False AutoWrap True NewLine True Scroll Jump ShowControls False SwapBackspaceDelete False TerminalMode VT52 ShowStatusBar False ShowTabRuler False InverseVideo False InsertChar False OriginAtMargin False KeyClick True CursorKey ANSI Keypad Numeric AnswerBack \"\" KeyboardLocked False ActiveCharSet G0 NRCSet USASCII G0 USASCII G1 USASCII G2 USASCII G3 USASCII"
  204. ;
  205.     int    len;
  206.     int                err;
  207.     
  208.     SysBeep(1);
  209.     SysBeep(1);
  210.     SysBeep(1);
  211.     SysBeep(1);
  212.     SysBeep(1);
  213.     SysBeep(1);
  214.     SysBeep(1);
  215.     SysBeep(1);
  216.  
  217.     procID = TMGetProcID(toolname);
  218.     windowRec = GetNewWindow(rWindow, NULL, (WindowPtr) -1);
  219.     theRectRec = windowRec->portRect;
  220.     windowSend = GetNewWindow(rWindowSend, NULL, (WindowPtr) -1);
  221.     theRectSend = windowSend->portRect;
  222.     gTermRec = TMNew(&theRectRec, &theRectRec, 0L, procID, windowRec, &TermSendProc,
  223.                   NULL, NULL, NULL, &ToolGetConnEnvirons, 0L, 0L);    
  224.  
  225.     gTerm = TMNew(&theRectSend, &theRectSend, 0L, procID, windowSend, &TermSendProc,
  226.                   NULL, NULL, NULL, &ToolGetConnEnvirons, 0L, 0L);    
  227.  
  228. //    SetPt(&where,10,40);
  229. //    TMChoose(&gTerm, where, NULL);
  230. //    configStr = TMGetConfig(gTerm);
  231.     err = TMSetConfig(gTerm, configStr);
  232.     err = TMSetConfig(gTermRec, configStr);
  233.     gGreetingData[(u_short)gGreetingData[0]+1] = '\n';
  234.     (gGreetingData[0]) += 1; 
  235.     gGreetingData[(u_short)gGreetingData[0]+1] = 0x00;
  236.     len = gGreetingData[0]+1;
  237.     PtoCstr(gGreetingData);
  238.     send(iopb->tcpBlock.tcpStream, (char *)gGreetingData, 
  239.                 len, 0L);
  240.     StoreConnectedPBlock(iopb);
  241.     gTimeCount = 1;
  242. //    RecycleFreePBlock(iopb);
  243. //    iopb = GetUnusedPBlock();
  244. //    if (iopb)
  245. //        StartListener(&iopb->tcpBlock);
  246. }
  247.  
  248.  
  249. void    DoTalking(MyQElemPtr iopb)
  250. {
  251.     long    len;
  252.     int        err;
  253.     CMFlags    flags = 0L;
  254.     static    long    deltaTime;
  255.             if (gTimeCount == 1) {
  256.                 gTimeCount = 2;
  257.                 recve(&iopb->tcpBlock, gRecvBuffer, kRcvBuffSize, 0L);
  258.             }
  259.             
  260.             if ((iopb->tcpBlock.ioResult == 0) && 
  261.                 (iopb->tcpBlock.csParam.receive.rcvBuffLen > 0)) {
  262.                     len = TMStream(gTermRec,gRecvBuffer, iopb->tcpBlock.csParam.receive.rcvBuffLen, flags);
  263.                     recve(&iopb->tcpBlock, gRecvBuffer, kRcvBuffSize, 0L);
  264.                 } else 
  265.                 if ((iopb->tcpBlock.ioResult == 0) && 
  266.                     (iopb->tcpBlock.csParam.receive.rcvBuffLen == 0)){ 
  267.                 } else 
  268.                 if (iopb->tcpBlock.ioResult < 0) {
  269.                     printf( "error on recieve: %d",iopb->tcpBlock.ioResult );
  270.                 }
  271.  
  272.             
  273.         if (!gNoSendDataPending){
  274.             len = strlen(gSendBuffer);
  275.             err = send(iopb->tcpBlock.tcpStream, gSendBuffer, len, 0L);
  276.             gNoSendDataPending = TRUE;
  277.             }
  278.     TMIdle(gTerm);
  279.     TMIdle(gTermRec);
  280. }
  281.  
  282. /* another, acyncronous implementation of recv */
  283.  
  284. long recve (TCPiopb *pBlock, char *buf, long len, long flags)
  285. {
  286.     OSErr         err;
  287.  
  288.     
  289.     pBlock->ioCRefNum = gRefNum;
  290.     pBlock->csCode = TCPRcv;
  291.     pBlock->ioResult = 1;
  292.     pBlock->ioCompletion = 0L;
  293. //    pBlock->tcpStream = stream;
  294.     pBlock->csParam.receive.commandTimeoutValue = 0x00;
  295.     pBlock->csParam.receive.rcvBuff = buf;
  296.     pBlock->csParam.receive.rcvBuffLen = len;
  297.     PBControl((ParmBlkPtr)pBlock,true);
  298.     return noErr;
  299.  
  300.  
  301.  
  302. }
  303.  
  304.  
  305.  
  306.  
  307.  
  308. /*    here, we send some data to the remote host over the opened connection and close the connection
  309.     when done.  if we didn't use os queues, this code would be much more complicated, since it
  310.     would have to be interrupt safe, and we would have to perform all driver calls async with
  311.     linked completion routines (yuck)
  312. */
  313. /*
  314. void SendData(TCPiopb *pBlock,StringPtr data)
  315. {
  316.     OSErr err;
  317.     wdsEntry wdsPtr[4];
  318.     char crlf[] = "\015\012";
  319.  
  320.     wdsPtr[0].length = wdsPtr[2].length = 2;
  321.     wdsPtr[0].ptr = wdsPtr[2].ptr = crlf;
  322.     wdsPtr[1].length = data[0];
  323.     wdsPtr[1].ptr = (void *)&data[1];
  324.     wdsPtr[3].length = 0;
  325.     wdsPtr[3].ptr = nil;
  326.  
  327.     pBlock->csCode = TCPSend;
  328.     pBlock->ioCRefNum = gTcpDrvrRef;
  329.     pBlock->csParam.send.ulpTimeoutValue = 0;
  330.     pBlock->csParam.send.ulpTimeoutAction = 1;
  331.     pBlock->csParam.send.validityFlags = 0xc0;
  332.     pBlock->csParam.send.pushFlag = false;
  333.     pBlock->csParam.send.urgentFlag = false;
  334.     pBlock->csParam.send.wdsPtr = (Ptr)wdsPtr;
  335.     err = PBControl(pBlock,false);
  336.     if (err!=noErr)
  337.         DoError(err);
  338.  
  339.     pBlock->csCode = TCPClose;
  340.     pBlock->ioCRefNum = gTcpDrvrRef;
  341.     pBlock->csParam.close.validityFlags = 0xC0;
  342.     pBlock->csParam.close.ulpTimeoutValue = 20;
  343.     pBlock->csParam.close.ulpTimeoutAction = 1;
  344.     err = PBControl(pBlock,false);
  345.     if (err!=noErr)
  346.         DoError(err);
  347.     
  348.     pBlock->csCode = TCPRelease;
  349.     pBlock->ioCRefNum = gTcpDrvrRef;
  350.     err = PBControl(pBlock,false);
  351.     if (err!=noErr)
  352.         DoError(err);
  353. }
  354. */